/**
 * @class Customer
 * @method buildDom 插入DOM
 * @method flashIndex 更新等待队列
 * @method addTag 添加进度条
 * @method startTimer 开始计时
 * @method findEmptyDesk 找到第一个空桌子
 * @method flashIndex 刷新当前排位号
 * @method addTag 添加标签(等位中/菜名)
 * @method refreshFoodWaitProcess 刷新等待食物/进食进度条
 * @method refreshSitWaitProcess 刷新等位进度条
 * @method grayTag 将进度条变灰(当一个食物等待超时时)
 * @method addRecept 点单后用户接收菜单
 * @method saveFood 用户从厨师处获得一道菜
 * @method tryEating 尝试去吃(如果有食物在等待被吃队列)
 * @method pay 付款并走人
 * @method toSad 一道菜都没有等到时
 * @method back 离开
 */

class Customer {
  constructor(
    id,
    userName = restaurant.config.customerNames[
      Number.parseInt(
        Math.random() * restaurant.config.customerNames.length,
        10,
      ) % restaurant.config.customerNames.length
    ],
  ) {
    this.id = id;
    this.userName = userName;
    this.onWaitIdx = restaurant.customers.length;
    this.onWait = this.onWaitIdx >= restaurant.config.customerMax;
    this.ele = null;
    this.pic =
      Number.parseInt(Math.random() * restaurant.config.customerPic, 10) %
      restaurant.config.customerPic;
    this.colorStyle =
      Number.parseInt(Math.random() * restaurant.config.colors.length, 10) %
      restaurant.config.colors.length;
    this.havingFoods = [];
    this.curWaits = [];
    this.curSad = 0;
    this.waitToEat = [];
    this.onEating = false;
    this.buildDom();
  }

  buildDom() {
    if (this.ele) this.ele.remove();
    this.ele = restaurant.customerDefaultEle.cloneNode(true);
    restaurant.addProcess(this.ele, this.colorStyle);
    this.tags = this.ele.querySelector('.tags');
    this.ele
      .querySelector('img')
      .setAttribute('src', `./img/cus-${this.pic}.png`);
    this.flashIndex();
    if (this.onWait) {
      this.ele.classList.replace('customer', 'customerWait');
      this.tags.classList.add('tags-bottom');
      const tag = this.addTag('等位中');
      restaurant.customersWaitEle.appendChild(this.ele);
      this.waitSitTimer = new Timer(
        100,
        restaurant.config.customerWaitForSite,
        () => window.game.pause,
        () => {
          this.refreshSitWaitProcess(
            tag,
            this.waitSitTimer,
            restaurant.config.customerWaitForSite,
          );
        },
        () => {
          this.isTimeOut = true;
          new AlertBox(
            `顾客${this.userName}等不到位置走了, 呜呜呜~`,
            2000,
            'error',
          );
          this.back();
        },
      );
      this.waitSitTimer.start();
    } else {
      this.tags.classList.add('tags-right');
      const emptyDish = this.findEmptyDesk();
      restaurant.customersEle.replaceChild(this.ele, emptyDish);
      restaurant.customerEleArr = restaurant.customersEle.children;
      this.menu = new Menu(
        this,
        restaurant.config.foods,
        restaurant.config.menu,
      );
    }
  }

  findEmptyDesk() {
    return restaurant.customersEle.querySelector('.delPeople');
  }

  flashIndex() {
    const tryIdx = restaurant.customers.findIndex((d) => d === this);
    this.onWaitIdx = tryIdx === -1 ? this.onWaitIdx : tryIdx;
    this.onWait = this.onWaitIdx >= restaurant.config.customerMax;
  }

  addTag(text) {
    const tag = document.createElement('div');
    tag.classList.add('tag');
    tag.innerHTML = `
      <div class="process LR">
        <div class="haveWork"></div>
      </div>
      <div class="box-text">${text}</div>
    `;
    restaurant.addProcess(tag, this.colorStyle);
    this.tags.appendChild(tag);
    return tag;
  }

  refreshFoodWaitProcess(f, totle) {
    const passed = f.timer.count;
    f.tagEle.querySelector('.haveWork').style.width = `${
      (passed / totle) * 100
    }%`;
  }

  refreshSitWaitProcess(tag, timer, totle) {
    const passed = timer.count;
    tag.querySelector('.haveWork').style.width = `${(passed / totle) * 100}%`;
  }

  grayTag(f) {
    f.tagEle.classList.add('missed');
  }

  addRecept(arr) {
    this.curSad = 0;
    arr.forEach((d) => {
      const food = restaurant.config.foods[d];
      const tagEle = this.addTag(food.foodName);
      const f = {
        food,
        tagEle,
        isTimeOut: false,
        haveGet: false,
      };
      f.timer = new Timer(
        100,
        food.patient,
        () => window.game.pause,
        () => {
          this.refreshFoodWaitProcess(f, f.food.patient);
        },
        () => {
          f.isTimeOut = true;
          this.grayTag(f);
          if (++this.curSad === this.curWaits.length) this.toSad();
        },
      );
      f.timer.start();
      this.curWaits.push(f);
    });
  }

  saveFood(idx) {
    const f = this.curWaits[idx];
    f.haveGet = true;
    f.isTimeOut = false;
    f.timer.clear();
    f.timer = new Timer(
      100,
      f.food.haveTime,
      () => window.game.pause,
      () => {
        this.refreshFoodWaitProcess(f, f.food.haveTime);
        f.tagEle.classList.add('having');
      },
      () => {
        f.isTimeOut = true;
        this.pay(f);
        this.onEating = false;
        this.tryEating();
      },
    );
    this.waitToEat.push(f);
    this.tryEating();
  }

  tryEating() {
    if (this.onEating) return false;
    this.waitToEat[0]?.timer.start();
  }

  pay(f) {
    restaurant.state.money += f.food.price;
    new AlertBox(
      `${this.userName}支付了${f.food.price}元(${f.food.foodName})ヽ(✿ﾟ▽ﾟ)ノ`,
      2000,
    );
    this.waitToEat.shift();
    if (
      this.waitToEat.length == 0 &&
      this.onEating === false &&
      this.curWaits.findIndex((d) => !d.haveGet && !d.isTimeOut) === -1
    ) {
      this.back();
    }
  }

  toSad() {
    new AlertBox(
      `${this.userName}失望而归，别再让客人挨饿了orz`,
      2000,
      'error',
    );
    this.back();
  }

  back() {
    restaurant.delCustom(this);
  }
}
